﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Vin.Extension.Framework.Monitor.Constants;
using Vin.Extension.Framework.Monitor.Entities;
using Vin.Extension.Framework.Monitor.Options;
using Vin.Extension.Framework.Monitor.ServiceInterface;
using Vin.Extension.Redis.Cache;
using Vin.Tool.AspNetCore.Singleton;
using Vin.Tool.Core.BasicTypeCategory;

namespace Vin.Extension.Framework.Monitor.BackgroundServices;

public class OperateLogBackgroundService : BackgroundService
{
    private IOptionsMonitor<MonitorOption> _optionsMonitor;
    private MonitorOption Option => _optionsMonitor.CurrentValue;

    public OperateLogBackgroundService(IOptionsMonitor<MonitorOption> optionsMonitor)
    {
        _optionsMonitor = optionsMonitor;
    }

    private Task ProcessAsync(int index, CancellationToken stoppingToken)
    {
        return VinApp.CreateScopeAsync(async provider =>
        {
            try
            {
                var redisCache = RedisCacheManager.GetRedisCache();
                var operateLogService = provider.GetRequiredService<ISysOperateLogService>();
                while (!stoppingToken.IsCancellationRequested)
                {
                    long cursor = 0;

                    do
                    {
                        var result = await redisCache.ScanAsync(cursor,
                            MonitorConstants.OperateLogKey.Format(index, "*"),
                            Option.BatchSize);
                        cursor = result.cursor;

                        var list = result.items.ToList();

                        #region 处理数据

                        foreach (var key in list)
                        {
                            var log = await redisCache.GetCacheAsync<SysOperateLog>(key);
                            if (log != null)
                            {
                                if (await operateLogService.SaveAsync(log))
                                {
                                    await redisCache.RemoveCacheAsync(key);
                                }
                            }
                        }

                        #endregion
                    } while (cursor > 0);

                    // 如果没有数据则等待5秒
                    await Task.Delay(Option.WaitSeconds * 1000);
                }
            }
            catch (System.Exception e)
            {
                provider.GetRequiredService<ILogger<OperateLogBackgroundService>>()
                    .LogError(e, "OperateLogBackgroundService Error");
                await Task.Delay(5000);
            }
        });
    }


    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var tasks = new List<Task>();
        for (var i = 0; i < Option.ThreadSize; i++)
        {
            tasks.Add(ProcessAsync(i, stoppingToken));
        }

        await Task.WhenAll(tasks);
    }
}

// using Microsoft.Extensions.DependencyInjection;
// using Microsoft.Extensions.Hosting;
// using Microsoft.Extensions.Logging;
// using Vin.Extension.Framework.Monitor.Constants;
// using Vin.Extension.Framework.Monitor.Entities;
// using Vin.Extension.Framework.Monitor.ServiceInterface;
// using Vin.Extension.Redis.Cache;
// using Vin.Tool.AspNetCore.Singleton;
//
// namespace Vin.Extension.Framework.Monitor.BackgroundServices;
//
// public class OperateLogBackgroundService : BackgroundService
// {
//     private ILogger<OperateLogBackgroundService> _logger;
//
//     public OperateLogBackgroundService(ILogger<OperateLogBackgroundService> logger)
//     {
//         _logger = logger;
//     }
//
//     protected override async Task ExecuteAsync(CancellationToken stoppingToken)
//     {
//         await VinApp.CreateScopeAsync(async provider =>
//         {
//             var redisCache = RedisCacheManager.GetRedisCache();
//             var operateLogService = provider.GetRequiredService<ISysOperateLogService>();
//             while (!stoppingToken.IsCancellationRequested)
//             {
//                 var item = await redisCache.BlPopAsync<string>(MonitorConstants.OperateLogListKey, 3);
//                 if (item != null)
//                 {
//                     var log = await redisCache.GetCacheAsync<SysOperateLog>(item);
//                     if (log != null)
//                     {
//                         if (await operateLogService.SaveAsync(log))
//                         {
//                             await redisCache.RemoveCacheAsync(item);
//                             continue;
//                         }
//
//                         // 保存失败
//                         await redisCache.LPushAsync(MonitorConstants.OperateLogListKey, item);
//                         _logger.LogError("OperateLogBackgroundService SaveAsync Error：{0}", item);
//                     }
//                     else
//                     {
//                         await redisCache.LPushAsync(MonitorConstants.OperateLogListKey, item);
//                         _logger.LogError("OperateLogBackgroundService SaveAsync Error：{0}", item);
//                     }
//
//                     continue;
//                 }
//
//                 // 如果没有数据则等待5秒
//                 await Task.Delay(5000);
//             }
//         });
//     }
// }